package com.sunkyc.framework.system.conmponents;

import cn.dev33.satoken.stp.StpInterface;
import cn.dev33.satoken.stp.StpUtil;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.sunkyc.commons.contants.GlobContants;
import com.sunkyc.framework.system.CacheKey.AuthroticationCacheKeys;
import com.sunkyc.framework.system.entity.LoginRole;
import com.sunkyc.framework.system.mapper.MenuMapper;
import com.sunkyc.framework.system.mapper.RoleMapper;
import com.sunkyc.framework.utils.RedisUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;


/**
 * 自定义权限验证接口扩展
 */


@Slf4j
@Component
public class StpInterfaceImpl implements StpInterface {

    private RoleMapper roleMapper;
    private MenuMapper menuMapper;

    private RedisUtils redisUtils;

    @Autowired
    public StpInterfaceImpl(RoleMapper roleMapper, MenuMapper menuMapper, RedisUtils redisUtils) {
        this.roleMapper = roleMapper;
        this.menuMapper = menuMapper;
        this.redisUtils = redisUtils;
    }

    /**
     * 返回一个账号所拥有的角色标识集合 (权限与角色可分开校验)
     */
    @Override
    public List<String> getRoleList(Object loginId, String loginType) {
        String key = AuthroticationCacheKeys.AUTH_DATA_SCOPE_USER_ID_LIST + "_roles_key_#" + loginId;
        List<LoginRole> loginRoles = queryRoleList(StpUtil.getLoginIdAsLong());
        List<String> roles = redisUtils.getCacheList(key);
        if (CollectionUtils.isNotEmpty(roles)) return roles;
        roles = new ArrayList<>();
        Boolean isAdmin = checkAdmin(loginRoles);
        if (isAdmin) {
            roles.add("*");
            roles.add(GlobContants.SUPER_ADMIN);
            return roles;
        } else {
            List<String> collect = loginRoles.stream().map(item -> item.getRoleKey()).collect(Collectors.toList());
            for (String roleKey : collect) {
                roles.add(roleKey);
            }
        }
        if (CollectionUtils.isNotEmpty(roles)) redisUtils.setCacheList(key, roles);
        return roles;
    }

    /**
     * 返回一个账号所拥有的权限码集合
     */
    @Override
    public List<String> getPermissionList(Object loginId, String loginType) {
        String key = AuthroticationCacheKeys.AUTH_DATA_SCOPE_USER_ID_LIST + "_permissions_" + loginId;
        List<LoginRole> loginRoles = queryRoleList(StpUtil.getLoginIdAsLong());
        List<String> permissions = redisUtils.getCacheList(key);
        if (CollectionUtils.isNotEmpty(permissions)) return permissions;
        permissions = new ArrayList<>();
        Boolean isAdmin = checkAdmin(loginRoles);
        if (isAdmin) {
            permissions.clear();
            permissions.add("*");
            return permissions;
        }
        // 遍历角色信息 获取对应的菜单标识
        else {
            for (LoginRole loginRole : loginRoles) {
                List<String> perems = queryPeremsListByRoleId(loginRole.getRoleId());
                if (CollectionUtils.isNotEmpty(perems)) {
                    permissions.addAll(perems);
                }
            }
        }
        permissions = permissions.stream().distinct().collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(permissions)) {
            redisUtils.setCacheList(key, permissions);
        }
        return permissions;
    }


    /**
     * 根据用户id获取角色列表
     *
     * @param userId
     * @return
     */
    private List<LoginRole> queryRoleList(Long userId) {
        String key = AuthroticationCacheKeys.AUTH_DATA_SCOPE_USER_ID_LIST + "_roles_#" + userId;
        List<LoginRole> loginRoles = redisUtils.getCacheList(key);
        if (CollectionUtils.isNotEmpty(loginRoles)) return loginRoles;
        loginRoles = roleMapper.queryLoginRoleByUserId(userId);
        if (CollectionUtils.isNotEmpty(loginRoles)) redisUtils.setCacheList(key,loginRoles);
        return loginRoles;
    }

    /**
     * 给定一个角色列表，判断是否是超级管理员
     *
     * @param list
     * @return
     */
    public Boolean checkAdmin(List<LoginRole> list) {
        boolean falg = false;
        for (LoginRole loginRole : list) {
            if (GlobContants.SUPER_ADMIN.equals(loginRole.getRoleKey())) {
                falg = true;
                break;
            }
        }
        return falg;
    }

    /**
     * 根据角色id查询对应菜单权限标识集合
     *
     * @param roleId
     * @return
     */
    private List<String> queryPeremsListByRoleId(Long roleId) {
        String key = AuthroticationCacheKeys.AUTH_DATA_SCOPE_USER_ID_LIST + "_roles_menu_perems_#" + roleId;
        List<String> perems = redisUtils.getCacheList(key);
        if(CollectionUtils.isNotEmpty(perems)) return perems;
        perems = menuMapper.queryMenuPeremsByRoleId(roleId);
        if(CollectionUtils.isNotEmpty(perems)) redisUtils.setCacheList(key,perems);
        return perems;
    }


}
